home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume1 / ansi.c next >
Encoding:
Internet Message Format  |  1986-11-30  |  14.6 KB

  1. Date: Fri, 10 May 85 13:54:41 edt
  2. From: Arnold Robbins <gatech!arnold>
  3. Subject: Yacc and Lex for 11/12/84 draft of ANSI C
  4. Newsgroups: mod.sources
  5.  
  6. Due to popular request on net.lang.c, I am reposting the Yacc and Lex
  7. descriptions of the 11/12/84 draft of ANSI C.  Many people have wanted
  8. this to make it into a grammar for regular C, for their C compilers.
  9.  
  10. Arnold Robbins
  11. gatech!arnold
  12. --------------------- cut here ----------------------------
  13. #!/bin/sh
  14. # This is a shell archive, meaning:
  15. # 1. Remove everything above the #!/bin/sh line.
  16. # 2. Save the resulting text in a file.
  17. # 3. Execute the file with /bin/sh (not csh) to create the files:
  18. #    README
  19. #    Makefile
  20. #    gram.y
  21. #    scan.l
  22. #    main.c
  23. # This archive created: Fri May 10 13:51:08 1985
  24. # By:    Arnold Robbins (Pr1mebusters!)
  25. export PATH; PATH=/bin:$PATH
  26. echo shar: extracting "'README'" '(1419 characters)'
  27. if test -f 'README'
  28. then
  29.     echo shar: over-writing existing file "'README'"
  30. fi
  31. cat << \SHAR_EOF > 'README'
  32. The files in this directory contain the ANSI C grammar from the Nov 12, 1984
  33. draft of the standard.  Note that a newer draft has come out since then.
  34. I have applied the two bug fixes I have seen reported on the net for this
  35. grammar.
  36.  
  37. With a little work, this grammar can be made to parse regular C.
  38. I am reposting it, due to popular demand.  Credit for creating this in
  39. the first place goes to my office mate, Jeff Lee, gatech!jeff.
  40.  
  41. Here is his original note:
  42. > This is the current (Nov 12, 1984) draft of the C grammar in Yacc form
  43. > with a little scanner I wrote in Lex so that you end up with a complete
  44. > program with which you can amaze and befuddle your friends. Or you can
  45. > sit and crank your own output through it to amuse yourself if you have the
  46. > personality of a cumquat(sp?). This contains nothing to handle preprocessor
  47. > stuff nor to handle "#line" directives so you must remove these beforehand
  48. > to allow it to parse the stuff. Also, it bypasses the typedef problem
  49. > by always returning an IDENTIFIER when it encounters anything that looks
  50. > like an IDENTIFIER, but it has a little stub in place where you would put
  51. > your symbol table lookup to determine if it a typedef or not. Other than
  52. > that, this is all yours. Wear it in good health and if anyone asks, just say
  53. > I told you so. Oh, by the way..... this is in 'shar' format, so you know
  54. > what to do.
  55.  
  56. Arnold Robbins
  57. gatech!arnold
  58. May, 1985
  59. SHAR_EOF
  60. echo shar: extracting "'Makefile'" '(167 characters)'
  61. if test -f 'Makefile'
  62. then
  63.     echo shar: over-writing existing file "'Makefile'"
  64. fi
  65. cat << \SHAR_EOF > 'Makefile'
  66. YFLAGS    = -d
  67. CFLAGS    = -O
  68. LFLAGS    =
  69.  
  70. SRC    = gram.y scan.l main.c
  71. OBJ    = gram.o scan.o main.o
  72.  
  73. a.out    : $(OBJ)
  74.     cc $(OBJ)
  75.  
  76. scan.o    : y.tab.h
  77.  
  78. clean    :
  79.     rm -f a.out y.tab.h *.o
  80. SHAR_EOF
  81. echo shar: extracting "'gram.y'" '(7344 characters)'
  82. if test -f 'gram.y'
  83. then
  84.     echo shar: over-writing existing file "'gram.y'"
  85. fi
  86. cat << \SHAR_EOF > 'gram.y'
  87. %token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
  88. %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
  89. %token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
  90. %token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
  91. %token XOR_ASSIGN OR_ASSIGN TYPE_NAME
  92.  
  93. %token TYPEDEF EXTERN STATIC AUTO REGISTER
  94. %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
  95. %token STRUCT UNION ENUM ELIPSIS RANGE
  96.  
  97. %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
  98.  
  99. %start file
  100. %%
  101.  
  102. primary_expr
  103.     : identifier
  104.     | CONSTANT
  105.     | STRING_LITERAL
  106.     | '(' expr ')'
  107.     | primary_expr '[' expr ']'
  108.     | primary_expr '(' ')'
  109.     | primary_expr '(' argument_expr_list ')'
  110.     | primary_expr '.' identifier
  111.     | primary_expr PTR_OP identifier
  112.     ;
  113.  
  114. argument_expr_list
  115.     : assignment_expr
  116.     | argument_expr_list ',' assignment_expr
  117.     ;
  118.  
  119. postfix_expr
  120.     : primary_expr
  121.     | primary_expr INC_OP
  122.     | primary_expr DEC_OP
  123.     ;
  124.  
  125. unary_expr
  126.     : postfix_expr
  127.     | INC_OP unary_expr
  128.     | DEC_OP unary_expr
  129.     | unary_operator cast_expr
  130.     | SIZEOF unary_expr
  131.     | SIZEOF '(' type_name ')'
  132.     ;
  133.  
  134. unary_operator
  135.     : '&'
  136.     | '*'
  137.     | '+'
  138.     | '-'
  139.     | '~'
  140.     | '!'
  141.     ;
  142.  
  143. cast_expr
  144.     : unary_expr
  145.     | '(' type_name ')' cast_expr
  146.     ;
  147.  
  148. multiplicative_expr
  149.     : cast_expr
  150.     | multiplicative_expr '*' cast_expr
  151.     | multiplicative_expr '/' cast_expr
  152.     | multiplicative_expr '%' cast_expr
  153.     ;
  154.  
  155. additive_expr
  156.     : multiplicative_expr
  157.     | additive_expr '+' multiplicative_expr
  158.     | additive_expr '-' multiplicative_expr
  159.     ;
  160.  
  161. shift_expr
  162.     : additive_expr
  163.     | shift_expr LEFT_OP additive_expr
  164.     | shift_expr RIGHT_OP additive_expr
  165.     ;
  166.  
  167. relational_expr
  168.     : shift_expr
  169.     | relational_expr '<' shift_expr
  170.     | relational_expr '>' shift_expr
  171.     | relational_expr LE_OP shift_expr
  172.     | relational_expr GE_OP shift_expr
  173.     ;
  174.  
  175. equality_expr
  176.     : relational_expr
  177.     | equality_expr EQ_OP relational_expr
  178.     | equality_expr NE_OP relational_expr
  179.     ;
  180.  
  181. and_expr
  182.     : equality_expr
  183.     | and_expr '&' equality_expr
  184.     ;
  185.  
  186. exclusive_or_expr
  187.     : and_expr
  188.     | exclusive_or_expr '^' and_expr
  189.     ;
  190.  
  191. inclusive_or_expr
  192.     : exclusive_or_expr
  193.     | inclusive_or_expr '|' exclusive_or_expr
  194.     ;
  195.  
  196. logical_and_expr
  197.     : inclusive_or_expr
  198.     | logical_and_expr AND_OP inclusive_or_expr
  199.     ;
  200.  
  201. logical_or_expr
  202.     : logical_and_expr
  203.     | logical_or_expr OR_OP logical_and_expr
  204.     ;
  205.  
  206. conditional_expr
  207.     : logical_or_expr
  208.     | logical_or_expr '?' logical_or_expr ':' conditional_expr
  209.     ;
  210.  
  211. assignment_expr
  212.     : conditional_expr
  213.     | unary_expr assignment_operator assignment_expr
  214.     ;
  215.  
  216. assignment_operator
  217.     : '='
  218.     | MUL_ASSIGN
  219.     | DIV_ASSIGN
  220.     | MOD_ASSIGN
  221.     | ADD_ASSIGN
  222.     | SUB_ASSIGN
  223.     | LEFT_ASSIGN
  224.     | RIGHT_ASSIGN
  225.     | AND_ASSIGN
  226.     | XOR_ASSIGN
  227.     | OR_ASSIGN
  228.     ;
  229.  
  230. expr
  231.     : assignment_expr
  232.     | expr ',' assignment_expr
  233.     ;
  234.  
  235. constant_expr
  236.     : conditional_expr
  237.     ;
  238.  
  239. declaration
  240.     : declaration_specifiers ';'
  241.     | declaration_specifiers init_declarator_list ';'
  242.     ;
  243.  
  244. declaration_specifiers
  245.     : ssc_specifier
  246.     | ssc_specifier declaration_specifiers
  247.     | type_specifier
  248.     | type_specifier declaration_specifiers
  249.     ;
  250.  
  251. init_declarator_list
  252.     : init_declarator
  253.     | init_declarator_list ',' init_declarator
  254.     ;
  255.  
  256. init_declarator
  257.     : declarator
  258.     | declarator '=' initializer
  259.     ;
  260.  
  261. ssc_specifier
  262.     : TYPEDEF
  263.     | EXTERN
  264.     | STATIC
  265.     | AUTO
  266.     | REGISTER
  267.     ;
  268.  
  269. type_specifier
  270.     : CHAR
  271.     | SHORT
  272.     | INT
  273.     | LONG
  274.     | SIGNED
  275.     | UNSIGNED
  276.     | FLOAT
  277.     | DOUBLE
  278.     | CONST
  279.     | VOLATILE
  280.     | VOID
  281.     | struct_or_union_specifier
  282.     | enum_specifier
  283.     | TYPE_NAME
  284.     ;
  285.  
  286. struct_or_union_specifier
  287.     : struct_or_union identifier '{' struct_declaration_list '}'
  288.     | struct_or_union '{' struct_declaration_list '}'
  289.     | struct_or_union identifier
  290.     ;
  291.  
  292. struct_or_union
  293.     : STRUCT
  294.     | UNION
  295.     ;
  296.  
  297. struct_declaration_list
  298.     : struct_declaration
  299.     | struct_declaration_list struct_declaration
  300.     ;
  301.  
  302. struct_declaration
  303.     : type_specifier_list struct_declarator_list ';'
  304.     ;
  305.  
  306. struct_declarator_list
  307.     : struct_declarator
  308.     | struct_declarator_list ',' struct_declarator
  309.     ;
  310.  
  311. struct_declarator
  312.     : declarator
  313.     | ':' constant_expr
  314.     | declarator ':' constant_expr
  315.     ;
  316.  
  317. enum_specifier
  318.     : ENUM '{' enumerator_list '}'
  319.     | ENUM identifier '{' enumerator_list '}'
  320.     | ENUM identifier
  321.     ;
  322.  
  323. enumerator_list
  324.     : enumerator
  325.     | enumerator_list ',' enumerator
  326.     ;
  327.  
  328. enumerator
  329.     : identifier
  330.     | identifier '=' constant_expr
  331.     ;
  332.  
  333. declarator
  334.     : declarator2
  335.     | pointer declarator2
  336.     ;
  337.  
  338. declarator2
  339.     : identifier
  340.     | '(' declarator ')'
  341.     | declarator2 '[' ']'
  342.     | declarator2 '[' constant_expr ']'
  343.     | declarator2 '(' ')'
  344.     | declarator2 '(' parameter_declaration_list ')'
  345.     ;
  346.  
  347. pointer
  348.     : '*'
  349.     | '*' type_specifier_list
  350.     | '*' pointer
  351.     | '*' type_specifier_list pointer
  352.     ;
  353.  
  354. type_specifier_list
  355.     : type_specifier
  356.     | type_specifier_list type_specifier
  357.     ;
  358.  
  359. parameter_declaration_list
  360.     : identifier_list
  361.     | identifier_list ',' ELIPSIS
  362.     | parameter_types
  363.     ;
  364.  
  365. identifier_list
  366.     : identifier
  367.     | identifier_list ',' identifier
  368.     ;
  369.  
  370. parameter_types
  371.     : parameter_list
  372.     | parameter_list ',' ELIPSIS
  373.     ;
  374.  
  375. parameter_list
  376.     : parameter_declaration
  377.     | parameter_list ',' parameter_declaration
  378.     ;
  379.  
  380. parameter_declaration
  381.     : type_specifier_list declarator
  382.     | type_name
  383.     ;
  384.  
  385. type_name
  386.     : type_specifier_list
  387.     | type_specifier_list abstract_declarator
  388.     ;
  389.  
  390. abstract_declarator
  391.     : pointer
  392.     | abstract_declarator2
  393.     | pointer abstract_declarator2
  394.     ;
  395.  
  396. abstract_declarator2
  397.     : '(' abstract_declarator ')'
  398.     | '[' ']'
  399.     | '[' constant_expr ']'
  400.     | abstract_declarator2 '[' ']'
  401.     | abstract_declarator2 '[' constant_expr ']'
  402.     | '(' ')'
  403.     | '(' parameter_types ')'
  404.     | abstract_declarator2 '(' ')'
  405.     | abstract_declarator2 '(' parameter_types ')'
  406.     ;
  407.  
  408. initializer
  409.     : assignment_expr
  410.     | '{' initializer_list '}'
  411.     | '{' initializer_list ',' '}'
  412.     ;
  413.  
  414. initializer_list
  415.     : initializer
  416.     | initializer_list ',' initializer
  417.     ;
  418.  
  419. statement
  420.     : labeled_statement
  421.     | compound_statement
  422.     | expression_statement
  423.     | selection_statement
  424.     | iteration_statement
  425.     | jump_statement
  426.     ;
  427.  
  428. labeled_statement
  429.     : identifier ':' statement
  430.     | CASE constant_expr ':' statement
  431.     | CASE constant_expr RANGE constant_expr ':' statement
  432.     | DEFAULT ':' statement
  433.     ;
  434.  
  435. compound_statement
  436.     : '{' '}'
  437.     | '{' statement_list '}'
  438.     | '{' declaration_list '}'
  439.     | '{' declaration_list statement_list '}'
  440.     ;
  441.  
  442. declaration_list
  443.     : declaration
  444.     | declaration_list declaration
  445.     ;
  446.  
  447. statement_list
  448.     : statement
  449.     | statement_list statement
  450.     ;
  451.  
  452. expression_statement
  453.     : ';'
  454.     | expr ';'
  455.     ;
  456.  
  457. selection_statement
  458.     : IF '(' expr ')' statement
  459.     | IF '(' expr ')' statement ELSE statement
  460.     | SWITCH '(' expr ')' statement
  461.     ;
  462.  
  463. iteration_statement
  464.     : WHILE '(' expr ')' statement
  465.     | DO statement WHILE '(' expr ')' ';'
  466.     | FOR '(' ';' ';' ')' statement
  467.     | FOR '(' ';' ';' expr ')' statement
  468.     | FOR '(' ';' expr ';' ')' statement
  469.     | FOR '(' ';' expr ';' expr ')' statement
  470.     | FOR '(' expr ';' ';' ')' statement
  471.     | FOR '(' expr ';' ';' expr ')' statement
  472.     | FOR '(' expr ';' expr ';' ')' statement
  473.     | FOR '(' expr ';' expr ';' expr ')' statement
  474.     ;
  475.  
  476. jump_statement
  477.     : GOTO identifier ';'
  478.     | CONTINUE ';'
  479.     | BREAK ';'
  480.     | RETURN ';'
  481.     | RETURN expr ';'
  482.     ;
  483.  
  484. file
  485.     : external_definition
  486.     | file external_definition
  487.     ;
  488.  
  489. external_definition
  490.     : function_definition
  491.     | declaration
  492.     ;
  493.  
  494. function_definition
  495.     : declarator function_body
  496.     | declaration_specifiers declarator function_body
  497.     ;
  498.  
  499. function_body
  500.     : compound_statement
  501.     | declaration_list compound_statement
  502.     ;
  503.  
  504. identifier
  505.     : IDENTIFIER
  506.     ;
  507. %%
  508.  
  509. #include <stdio.h>
  510.  
  511. extern char *yytext;
  512. extern int column;
  513.  
  514. yyerror(s)
  515. char *s;
  516. {
  517.     fflush(stdout);
  518.     printf("\n%*s\n%*s\n", column, "^", column, s);
  519. }
  520. SHAR_EOF
  521. echo shar: extracting "'scan.l'" '(4263 characters)'
  522. if test -f 'scan.l'
  523. then
  524.     echo shar: over-writing existing file "'scan.l'"
  525. fi
  526. cat << \SHAR_EOF > 'scan.l'
  527. D            [0-9]
  528. L            [a-zA-Z_]
  529. H            [a-fA-F0-9]
  530. E            [Ee][+-]?{D}+
  531. LS            (l|L)
  532. US            (u|U)
  533.  
  534. %{
  535. #include <stdio.h>
  536. #include "y.tab.h"
  537.  
  538. void count();
  539. %}
  540.  
  541. %%
  542. "/*"            { comment(); }
  543.  
  544. "auto"            { count(); return(AUTO); }
  545. "break"            { count(); return(BREAK); }
  546. "case"            { count(); return(CASE); }
  547. "char"            { count(); return(CHAR); }
  548. "const"            { count(); return(CONST); }
  549. "continue"        { count(); return(CONTINUE); }
  550. "default"        { count(); return(DEFAULT); }
  551. "do"            { count(); return(DO); }
  552. "double"        { count(); return(DOUBLE); }
  553. "else"            { count(); return(ELSE); }
  554. "enum"            { count(); return(ENUM); }
  555. "extern"        { count(); return(EXTERN); }
  556. "float"            { count(); return(FLOAT); }
  557. "for"            { count(); return(FOR); }
  558. "goto"            { count(); return(GOTO); }
  559. "if"            { count(); return(IF); }
  560. "int"            { count(); return(INT); }
  561. "long"            { count(); return(LONG); }
  562. "register"        { count(); return(REGISTER); }
  563. "return"        { count(); return(RETURN); }
  564. "short"            { count(); return(SHORT); }
  565. "signed"        { count(); return(SIGNED); }
  566. "sizeof"        { count(); return(SIZEOF); }
  567. "static"        { count(); return(STATIC); }
  568. "struct"        { count(); return(STRUCT); }
  569. "switch"        { count(); return(SWITCH); }
  570. "typedef"        { count(); return(TYPEDEF); }
  571. "union"            { count(); return(UNION); }
  572. "unsigned"        { count(); return(UNSIGNED); }
  573. "void"            { count(); return(VOID); }
  574. "volatile"        { count(); return(VOLATILE); }
  575. "while"            { count(); return(WHILE); }
  576.  
  577. {L}({L}|{D})*        { count(); return(check_type()); }
  578.  
  579. 0[xX]{H}+{LS}?{US}?    { count(); return(CONSTANT); }
  580. 0[xX]{H}+{US}?{LS}?    { count(); return(CONSTANT); }
  581. 0{D}+{LS}?{US}?        { count(); return(CONSTANT); }
  582. 0{D}+{US}?{LS}?        { count(); return(CONSTANT); }
  583. {D}+{LS}?{US}?        { count(); return(CONSTANT); }
  584. {D}+{US}?{LS}?        { count(); return(CONSTANT); }
  585. '(\\.|[^\\'])+'        { count(); return(CONSTANT); }
  586.  
  587. {D}+{E}{LS}?        { count(); return(CONSTANT); }
  588. {D}*"."{D}+({E})?{LS}?    { count(); return(CONSTANT); }
  589. {D}+"."{D}*({E})?{LS}?    { count(); return(CONSTANT); }
  590.  
  591. \"(\\.|[^\\"])*\"    { count(); return(STRING_LITERAL); }
  592.  
  593. ">>="            { count(); return(RIGHT_ASSIGN); }
  594. "<<="            { count(); return(LEFT_ASSIGN); }
  595. "+="            { count(); return(ADD_ASSIGN); }
  596. "-="            { count(); return(SUB_ASSIGN); }
  597. "*="            { count(); return(MUL_ASSIGN); }
  598. "/="            { count(); return(DIV_ASSIGN); }
  599. "%="            { count(); return(MOD_ASSIGN); }
  600. "&="            { count(); return(AND_ASSIGN); }
  601. "^="            { count(); return(XOR_ASSIGN); }
  602. "|="            { count(); return(OR_ASSIGN); }
  603. ">>"            { count(); return(RIGHT_OP); }
  604. "<<"            { count(); return(LEFT_OP); }
  605. "++"            { count(); return(INC_OP); }
  606. "--"            { count(); return(DEC_OP); }
  607. "->"            { count(); return(PTR_OP); }
  608. "&&"            { count(); return(AND_OP); }
  609. "||"            { count(); return(OR_OP); }
  610. "<="            { count(); return(LE_OP); }
  611. ">="            { count(); return(GE_OP); }
  612. "=="            { count(); return(EQ_OP); }
  613. "!="            { count(); return(NE_OP); }
  614. ";"            { count(); return(';'); }
  615. "{"            { count(); return('{'); }
  616. "}"            { count(); return('}'); }
  617. ","            { count(); return(','); }
  618. ":"            { count(); return(':'); }
  619. "="            { count(); return('='); }
  620. "("            { count(); return('('); }
  621. ")"            { count(); return(')'); }
  622. "["            { count(); return('['); }
  623. "]"            { count(); return(']'); }
  624. "."            { count(); return('.'); }
  625. "&"            { count(); return('&'); }
  626. "!"            { count(); return('!'); }
  627. "~"            { count(); return('~'); }
  628. "-"            { count(); return('-'); }
  629. "+"            { count(); return('+'); }
  630. "*"            { count(); return('*'); }
  631. "/"            { count(); return('/'); }
  632. "%"            { count(); return('%'); }
  633. "<"            { count(); return('<'); }
  634. ">"            { count(); return('>'); }
  635. "^"            { count(); return('^'); }
  636. "|"            { count(); return('|'); }
  637. "?"            { count(); return('?'); }
  638.  
  639. [ \t\v\n\f]        { count(); }
  640. .            { /* ignore bad characters */ }
  641.  
  642. %%
  643.  
  644. yywrap()
  645. {
  646.     return(1);
  647. }
  648.  
  649. comment()
  650. {
  651.     char c, c1;
  652.  
  653. loop:
  654.     while ((c = input()) != '*' && c != 0)
  655.         putchar(c);
  656.  
  657.     if ((c1 = input()) != '/' && c != 0)
  658.     {
  659.         unput(c1);
  660.         goto loop;
  661.     }
  662.  
  663.     if (c != 0)
  664.         putchar(c1);
  665. }
  666.  
  667. int column = 0;
  668.  
  669. void count()
  670. {
  671.     int i;
  672.  
  673.     for (i = 0; yytext[i] != '\0'; i++)
  674.         if (yytext[i] == '\n')
  675.             column = 0;
  676.         else if (yytext[i] == '\t')
  677.             column += 8 - (column % 8);
  678.         else
  679.             column++;
  680.  
  681.     ECHO;
  682. }
  683.  
  684. int check_type()
  685. {
  686. /*
  687. * pseudo code --- this is what it should check
  688. *
  689. *    if (yytext == type_name)
  690. *        return(TYPE_NAME);
  691. *
  692. *    return(IDENTIFIER);
  693. */
  694.  
  695. /*
  696. *    it actually will only return IDENTIFIER
  697. */
  698.  
  699.     return(IDENTIFIER);
  700. }
  701. SHAR_EOF
  702. echo shar: extracting "'main.c'" '(48 characters)'
  703. if test -f 'main.c'
  704. then
  705.     echo shar: over-writing existing file "'main.c'"
  706. fi
  707. cat << \SHAR_EOF > 'main.c'
  708. main()
  709. {
  710.     int yyparse();
  711.  
  712.     return(yyparse());
  713. }
  714. SHAR_EOF
  715. #    End of shell archive
  716. exit 0
  717.  
  718.